package com.zhangdi.dwperms.realm;

import com.zhangdi.dwcache.CacheContents;

import com.zhangdi.dwperms.bo.ShiroAccount;
import com.zhangdi.dwperms.cache.CacheTokenService;
import com.zhangdi.dwperms.entity.Account;
import com.zhangdi.dwperms.exception.TokenExpiredException;
import com.zhangdi.dwperms.token.CacheToken;
import com.zhangdi.dwperms.token.MSToken;
import com.zhangdi.dwperms.token.TokenUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.springframework.beans.factory.annotation.Autowired;

public class JwtRealm extends BaseRealm {
    public JwtRealm() {
        super.setAuthenticationTokenClass(MSToken.class);
    }

    @Autowired
    CacheTokenService cacheTokenService;
    @Autowired
    TokenUtils tokenUtils;

    @Override
    public CredentialsMatcher getCredentialsMatcher() {
        return ((authenticationToken, authenticationInfo) -> true);
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        MSToken token = (MSToken) authenticationToken;

        //严格点 以后端缓存中没有，就代表是会话过期
        CacheToken cacheToken = cacheTokenService.get(token.cacheKey());
        if (null == cacheToken) {
            throw new UnknownAccountException();
        }

        if (!cacheToken.getAccess_token().equals(token.getCredentials())) {
            throw new UnknownAccountException();
        }

        if (TokenUtils.isExpired(cacheToken.getRefresh_timestamp())) {
            throw new TokenExpiredException();
        }

        if (TokenUtils.isExpired(token.expiration())) {
            //刷新access token
            String newAccessToken = tokenUtils.refreshAccessToken(token);
            token.setCredentials(newAccessToken);
            //放入缓存
            cacheToken.setAccess_token(newAccessToken);
            cacheTokenService.save(token.cacheKey(), cacheToken);
        }

        Account account = accountDao.findByUsername((String) token.getPrincipal());
        if (null == account) {
            throw new UnknownAccountException("验证失败，查无此用户");
        }
        ShiroAccount shiroAccount = new ShiroAccount();
        shiroAccount.setUsername(account.getUsername());
        shiroAccount.setUserId(account.getUser().getId());

        return new SimpleAuthenticationInfo(shiroAccount, null, getName());
    }
}
